package org.dromara.web.CssUtil.payUtil.bean;

import org.apache.commons.codec.binary.Base64;

import java.io.IOException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dromara.web.CssUtil.payUtil.CipherCharset;
import org.dromara.web.CssUtil.payUtil.RsaBase64KeyPair;

public class FuiouRsaCipher {
    private static final String KEY_ALGORITHM = "RSA";
    private static final String ALGORITHM_SHA1 = "SHA1withRSA";
    private static final String ALGORITHM_SHA2 = "SHA256withRSA";
    private static final String ALGORITHM_MD5RSA = "MD5WithRSA";

    static {
        try {
            Security.addProvider(new BouncyCastleProvider());
        } catch (Exception var1) {
            var1.printStackTrace();
        }

    }

    public FuiouRsaCipher() {
    }

    public static String sign2Base64(String base64PriRsa, String inputStr) {
        return sign2Base64ByAlg(base64PriRsa, inputStr, "SHA1withRSA", CipherCharset.getCharset());
    }

    public static String sign2Base64BySha2(String base64PriRsa, String inputStr) {
        return sign2Base64ByAlg(base64PriRsa, inputStr, "SHA256withRSA", CipherCharset.getCharset());
    }

    public static String sign2Base64ByMd5Rsa(String base64PriRsa, String inputStr) {
        return sign2Base64ByAlg(base64PriRsa, inputStr, "MD5WithRSA", CipherCharset.getCharset());
    }

    public static String sign2Base64(String base64PriRsa, String inputStr, String charset) {
        return sign2Base64ByAlg(base64PriRsa, inputStr, "SHA1withRSA", charset);
    }

    public static String sign2Base64BySha2(String base64PriRsa, String inputStr, String charset) {
        return sign2Base64ByAlg(base64PriRsa, inputStr, "SHA256withRSA", charset);
    }

    public static String sign2Base64ByMd5Rsa(String base64PriRsa, String inputStr, String charset) {
        return sign2Base64ByAlg(base64PriRsa, inputStr, "MD5WithRSA", charset);
    }

    private static String sign2Base64ByAlg(String base64PriRsa, String inputStr, String algorithm, String charset) {
        try {
            PrivateKey privateKey = genPrivateKey(base64PriRsa);
            Signature signature = Signature.getInstance(algorithm, "BC");
            signature.initSign(privateKey);
            signature.update(inputStr.getBytes(charset));
            return Base64.encodeBase64String(signature.sign());
        } catch (Exception var6) {
            var6.printStackTrace();
            throw new IllegalArgumentException("rsa签名异常");
        }
    }

    public static boolean verifySign(String base64PubRsa, String src, String base64SignValue) {
        return verifySignByAlg(base64PubRsa, src, base64SignValue, "SHA1withRSA", CipherCharset.getCharset());
    }

    public static boolean verifySignBySha2(String base64PubRsa, String src, String base64SignValue) {
        return verifySignByAlg(base64PubRsa, src, base64SignValue, "SHA256withRSA", CipherCharset.getCharset());
    }

    public static boolean verifySignByMd5Rsa(String base64PubRsa, String src, String base64SignValue) {
        return verifySignByAlg(base64PubRsa, src, base64SignValue, "MD5WithRSA", CipherCharset.getCharset());
    }

    public static boolean verifySign(String base64PubRsa, String src, String base64SignValue, String charset) {
        return verifySignByAlg(base64PubRsa, src, base64SignValue, "SHA1withRSA", charset);
    }

    public static boolean verifySignBySha2(String base64PubRsa, String src, String base64SignValue, String charset) {
        return verifySignByAlg(base64PubRsa, src, base64SignValue, "SHA256withRSA", charset);
    }

    public static boolean verifySignByMd5Rsa(String base64PubRsa, String src, String base64SignValue, String charset) {
        return verifySignByAlg(base64PubRsa, src, base64SignValue, "MD5WithRSA", charset);
    }

    private static boolean verifySignByAlg(String base64PubRsa, String src, String base64SignValue, String algorithm, String charset) {
        try {
            PublicKey publicKey = genPublicKey(base64PubRsa);
            Signature signature = Signature.getInstance(algorithm, "BC");
            signature.initVerify(publicKey);
            signature.update(src.getBytes(charset));
            return signature.verify(Base64.decodeBase64(base64SignValue));
        } catch (Exception var7) {
            var7.printStackTrace();
            throw new IllegalArgumentException("rsa验证签名异常");
        }
    }

    private static PrivateKey genPrivateKey(String base64Rsa) {
        try {
            KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64Rsa));
            return kf.generatePrivate(keySpec);
        } catch (Exception var3) {
            var3.printStackTrace();
            throw new IllegalArgumentException("初始化秘钥异常");
        }
    }

    private static PublicKey genPublicKey(String base64Rsa) {
        try {
            KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(base64Rsa));
            return kf.generatePublic(keySpec);
        } catch (Exception var3) {
            var3.printStackTrace();
            throw new IllegalArgumentException("初始化秘钥失败");
        }
    }

    public static String convertPubRsaFile2Str(String fileStr) {
        PublicKey pk = genPublicKey(fileStr);
        return Base64.encodeBase64String(pk.getEncoded());
    }

    public static String convertPriRsaFile2Str(String fileStr) {
        PrivateKey pk = genPrivateKey(fileStr);
        return Base64.encodeBase64String(pk.getEncoded());
    }

    public static String encryptByRsaPub(String src, String base64PubRsa) {
        try {
            PublicKey publicKey = genPublicKey(base64PubRsa);
            byte[] encryptBytes = encryptByKey(src.getBytes(CipherCharset.getCharset()), publicKey);
            return Base64.encodeBase64String(encryptBytes);
        } catch (Exception var4) {
            var4.printStackTrace();
            throw new IllegalArgumentException("rsa加密失败");
        }
    }

    public static String encryptByRsaPub(String src, String base64PubRsa, String charset) {
        try {
            PublicKey publicKey = genPublicKey(base64PubRsa);
            byte[] encryptBytes = encryptByKey(src.getBytes(charset), publicKey);
            return Base64.encodeBase64String(encryptBytes);
        } catch (Exception var5) {
            var5.printStackTrace();
            throw new IllegalArgumentException("rsa加密失败");
        }
    }

    public static String encryptByRsaPri(String src, String base64PubRsa) {
        try {
            PrivateKey privateKey = genPrivateKey(base64PubRsa);
            byte[] encryptBytes = encryptByKey(src.getBytes(CipherCharset.getCharset()), privateKey);
            return Base64.encodeBase64String(encryptBytes);
        } catch (Exception var4) {
            var4.printStackTrace();
            throw new IllegalArgumentException("rsa加密失败");
        }
    }

    public static String encryptByRsaPri(String src, String base64PubRsa, String charset) {
        try {
            PrivateKey privateKey = genPrivateKey(base64PubRsa);
            byte[] encryptBytes = encryptByKey(src.getBytes(charset), privateKey);
            return Base64.encodeBase64String(encryptBytes);
        } catch (Exception var5) {
            var5.printStackTrace();
            throw new IllegalArgumentException("rsa加密失败");
        }
    }

    public static String decryptByRsaPri(String base64Src, String base64PriRsa) {
        try {
            PrivateKey privateKey = genPrivateKey(base64PriRsa);
            return new String(decryptKey(Base64.decodeBase64(base64Src), privateKey), CipherCharset.getCharset());
        } catch (Exception var3) {
            var3.printStackTrace();
            throw new IllegalArgumentException("rsa解密失败");
        }
    }

    public static String decryptByRsaPri(String base64Src, String base64PriRsa, String charset) {
        try {
            PrivateKey privateKey = genPrivateKey(base64PriRsa);
            return new String(decryptKey(Base64.decodeBase64(base64Src), privateKey), charset);
        } catch (Exception var4) {
            var4.printStackTrace();
            throw new IllegalArgumentException("rsa解密失败");
        }
    }

    public static String decryptByRsaPub(String base64Src, String base64PriRsa) {
        try {
            PublicKey publicKey = genPublicKey(base64PriRsa);
            return new String(decryptKey(Base64.decodeBase64(base64Src), publicKey), CipherCharset.getCharset());
        } catch (Exception var3) {
            var3.printStackTrace();
            throw new IllegalArgumentException("rsa解密失败");
        }
    }

    public static String decryptByRsaPub(String base64Src, String base64PriRsa, String charset) {
        try {
            PublicKey publicKey = genPublicKey(base64PriRsa);
            return new String(decryptKey(Base64.decodeBase64(base64Src), publicKey), charset);
        } catch (Exception var4) {
            var4.printStackTrace();
            throw new IllegalArgumentException("rsa解密失败");
        }
    }

    private static byte[] encryptByKey(byte[] srcData, Key publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(1, publicKey);
            int blockSize = cipher.getOutputSize(srcData.length) - 11;
            byte[] encryptedData = null;

            for(int i = 0; i < srcData.length; i += blockSize) {
                byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));
                encryptedData = addAll(encryptedData, doFinal);
            }

            return encryptedData;
        } catch (Exception var7) {
            var7.printStackTrace();
            return null;
        }
    }

    private static byte[] decryptKey(byte[] srcData, Key key) {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(2, key);
            int blockSize = cipher.getOutputSize(srcData.length);
            byte[] decryptData = null;

            for(int i = 0; i < srcData.length; i += blockSize) {
                byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));
                decryptData = addAll(decryptData, doFinal);
            }

            return decryptData;
        } catch (Exception var7) {
            var7.printStackTrace();
            return null;
        }
    }

    private static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
        if (array == null) {
            return null;
        } else {
            if (startIndexInclusive < 0) {
                startIndexInclusive = 0;
            }

            if (endIndexExclusive > array.length) {
                endIndexExclusive = array.length;
            }

            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0) {
                return new byte[0];
            } else {
                byte[] subarray = new byte[newSize];
                System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
                return subarray;
            }
        }
    }

    private static byte[] addAll(byte[] array1, byte[] array2) {
        if (array1 == null) {
            return clone(array2);
        } else if (array2 == null) {
            return clone(array1);
        } else {
            byte[] joinedArray = new byte[array1.length + array2.length];
            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
            return joinedArray;
        }
    }

    public static byte[] clone(byte[] array) {
        return array == null ? null : (byte[])array.clone();
    }

    public static RsaBase64KeyPair genKeyPair(int size) {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            keyPairGen.initialize(size);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            byte[] publicBytes = keyPair.getPublic().getEncoded();
            byte[] privateBytes = keyPair.getPrivate().getEncoded();
            return new RsaBase64KeyPair(Base64.encodeBase64String(publicBytes), Base64.encodeBase64String(privateBytes));
        } catch (Exception var5) {
            var5.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) throws IOException {
        String rsa = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJMr8NnRV7ve7Y5FEBium/TsU0fK5NvzvFpsYxPAQhBXY+EN0Bi2JEg790C1njk9Q3U36u2JBDHAiDIomlgh6wWkJsFn7dghV/fCWSX1VVJ+dRINZy1432fRaJ8GqspvMneBpeLjBe94IwlWKpN+AOR+BNX8QL/uHmfCPlVQXos9AgMBAAECgYAzqbMs434m50UBMmFKKNF6kxNRGnpodBFktLO7FTybu/HF6TFp21a1PMe5IYhfk5AAsBZ6OCUOygWFhhdYZN+5W+dweF3kp1rLE4y5CjwqNlk/g22TAndf9znh/ltHFLvITToqu/eh/34tE1gyNxRbsi1olw/1wv8ZRjM3vtM9QQJBANvNwFq+CJHUyFzkXQB7+ycQFnY8wDq8Uw2Hv9ZMjgIntH7FSlJtdu5mAYPPo6f74slO5tFUMNP7EVppqsjYaNkCQQCraD6iKHo+OIlvvYIKiMXatJGD7N1GNhq5CrhUNPWLHwv/Ih2D3JJdF8IUZOPIJfUxTfM2fZYI+EVdsv6s4RcFAkAGjNYbnighOGcUJZYD6q3sVxVkRqEv3ubWs2HrH/Lna4l8caKqXCq8JfwLkod8/QugFiLYwBqIZqX4vMdjHtfZAkBsAl9dbWZCaPvpxp/4JWGPxDLhz9NLV/KU4bVvkoObq++yUHwKyGYOdVcd5MlIKOsNq5Hzp0Vw14lWVuF2bMxFAkBuNrZksvUULNIaWDKd4rQ6GVzUxXuIZW0ZE6atHYDiXPB4jVAjKRtLxZAV1qH9cr1zNJlcg+RbGYUdF9t4A9n5";
        System.out.println(genPublicKey(rsa));
    }
}
